package com.ruoyi.web.controller.system;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.aliyuncs.exceptions.ClientException;
import com.ruoyi.common.config.Global;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.framework.shiro.service.SysPasswordService;
import com.ruoyi.framework.shiro.token.UserNamePasswordAndMobileToken;
import com.ruoyi.framework.util.ShiroUtils;
import com.ruoyi.system.domain.SysUser;
import com.ruoyi.system.service.ISmsValidateCodeService;
import com.ruoyi.system.service.ISysUserService;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;

/**
 * 登录验证
 * 
 * @author ruoyi
 */
@Controller
public class SysLoginController extends BaseController
{
    //后台登录方式
    public static String LOGIN_TYPE_USERNAME = "username";
    public static String LOGIN_TYPE_MOBILE = "mobile";

    @Autowired
    private ISysUserService userService;
    @Autowired
    private SysPasswordService passwordService;
    @Autowired
    private ISmsValidateCodeService smsValidateCodeService;

    @GetMapping("/login")
    public String login(HttpServletRequest request, HttpServletResponse response)
    {
        // 如果是Ajax请求，返回Json字符串。
        if (ServletUtils.isAjaxRequest(request))
        {
            return ServletUtils.renderString(response, "{\"code\":\"1\",\"msg\":\"未登录或登录超时。请重新登录\"}");
        }

        return "login";
    }

    @PostMapping("/login")
    @ResponseBody
    public AjaxResult ajaxLogin(String username, String password, String loginType, String mobile, String vcode,
                                boolean rememberMe)
    {
        if (LOGIN_TYPE_USERNAME.equals(loginType)) {
            UserNamePasswordAndMobileToken token = new UserNamePasswordAndMobileToken(username, password, rememberMe);
            Subject subject = SecurityUtils.getSubject();
            try
            {
                subject.login(token);
                return success();
            }
            catch (AuthenticationException e)
            {
                String msg = "用户或密码错误";
                if (StringUtils.isNotEmpty(e.getMessage()))
                {
                    msg = e.getMessage();
                }
                return error(msg);
            }
        } else {
            UserNamePasswordAndMobileToken token = new UserNamePasswordAndMobileToken(mobile, rememberMe);
            Subject subject = SecurityUtils.getSubject();
            try {
                long expiryDate = Global.getInt("sms.vcode_expiryDate", 5) * 60;//短信有效期
                int result = smsValidateCodeService.validateCode(mobile, vcode, Constants.SMS_VCODE_TYPE_LOGIN, expiryDate);
                if (Constants.SMS_VALIDATE_RESULT_SUCCESS == result) {
                    subject.login(token);
                    return success("登录成功！");
                } else {
                    return error("验证码无效！");
                }
            } catch (AuthenticationException e) {
                String msg = "手机号码错误";
                if (StringUtils.isNotEmpty(e.getMessage())) {
                    msg = e.getMessage();
                }
                return error(msg);
            }
        }

    }

    @GetMapping("/unauth")
    public String unauth()
    {
        return "error/unauth";
    }

    /**
     * 发送验证码短信
     *
     * @param mobile 手机号码
     */
    @PostMapping("/sendVcode")
    @ResponseBody
    public AjaxResult sendVcode(String mobile, String type) {
        if (StringUtils.isEmpty(mobile)) {
            return error("手机号码不正确");
        }
        if (StringUtils.isEmpty(type)) {
            return error("验证码类型不正确");
        }
        //判断该手机号是否已注册
        SysUser user = userService.selectUserByPhoneNumber(mobile.trim());
        if (user == null) {
            return error("预留手机号有误，请联系管理员！");
        } else {
            //生成四位随机数
            String randomCode = RandomStringUtils.randomNumeric(4);

            long intervalDate = Global.getInt("njbjs.intervalDate", 1) * 60;//发送间隔
            long expiryDate = Global.getInt("njbjs.expiryDate", 5) * 60;//短信有效期

            //发送短信验证码
            smsValidateCodeService.smsSend(mobile, randomCode, type, intervalDate, expiryDate);
            return success();
        }
    }

    /**
     * 验证重置密码时的验证码是否正确有效
     * @param mobile
     * @return
     */
    @PostMapping("/checkVcode")
    @ResponseBody
    public AjaxResult checkVcode(String mobile, String vcode){
        long expiryDate = Global.getInt("sms.vcode_expiryDate", 5) * 60;//短信有效期
        int result = smsValidateCodeService.validateCode(mobile, vcode, Constants.SMS_VCODE_TYPE_RESETPWD, expiryDate);

        //验证码正确
        if (Constants.SMS_VALIDATE_RESULT_SUCCESS == result) {
            SysUser user = userService.selectUserByPhoneNumber(mobile);
            if (user != null && StringUtils.isNotEmpty(user.getLoginName())) {
                return success("验证通过！").put("loginName", user.getLoginName());
            } else {
                return error("用户不存在,联系管理员！");
            }
        } else {
            return error("验证码无效！");
        }
    }

    /**
     * 修改密码
     * @param newPassword
     * @param loginName
     * @return
     * @throws ClientException
     */
    @PostMapping("/saveNewPassword")
    @ResponseBody
    public AjaxResult saveNewPassword(String newPassword, String loginName, String mobile) {
        SysUser user = new SysUser();
        user.setPhonenumber(mobile);
        user.setSalt(ShiroUtils.randomSalt());
        user.setPassword(passwordService.encryptPassword(loginName, newPassword, user.getSalt()));
        //修改密码
        int r = userService.updatePasswordByPhone(user);
        if (r > 0) {
            return success("修改成功");
        } else {
            return error("修改失败！");
        }
    }

}
